package com.example.demoes.config;

import com.example.demoes.entity.RestBean;

import com.example.demoes.entity.dto.Account;
import com.example.demoes.entity.vo.response.AuthorizeVO;
import com.example.demoes.filter.JwtAuthorizeFilter;
import com.example.demoes.service.AccountService;
import com.example.demoes.utils.JwtUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class SecurityConfiguration {
      @Resource
      JwtUtils utils;
      @Resource
      JwtAuthorizeFilter jwtAuthorizeFilter;

      @Resource
      AccountService service;

      @Bean
      public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
          return http
                  .authorizeHttpRequests(conf -> conf
                          .requestMatchers("/api/auth/**","/error").permitAll()
                          .anyRequest().authenticated()
                    )
                  .formLogin(conf -> conf
                          .loginProcessingUrl("/api/auth/login")
                          .failureHandler(this::onAuthenticationFailure)
                          .successHandler(this::onAuthenticationSuccess)
                  )
                  .logout(conf -> conf
                          .logoutUrl("/api/auth/logout")
                          .logoutSuccessHandler(
                                  this::onLogoutSuccess
                          )
                  )
                  .exceptionHandling(conf -> conf
                          .authenticationEntryPoint(this::onUnauthorized)
                          .accessDeniedHandler(this::onAccessDeny)
                   )
                  .csrf(AbstractHttpConfigurer::disable)
                  .sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                  .addFilterBefore(jwtAuthorizeFilter, UsernamePasswordAuthenticationFilter.class)
                  .build();
      }
      private void onAccessDeny(HttpServletRequest request,
                             HttpServletResponse response,
                                AccessDeniedException exception) throws  IOException{
          response.setContentType("application/json;charset=utf-8");
          response.getWriter().write(RestBean.forbidden(exception.getMessage()).asJsonString());
      }

      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
          //  response.getWriter().write("Success");
          response.setContentType("application/json;charset=utf-8");
          User user = (User) authentication.getPrincipal();
          Account account = service.findAccountByNameOrEmail(user.getUsername());
          String token = utils.createJwt(user,account.getId(),account.getUsername());
          AuthorizeVO vo = new AuthorizeVO();
          BeanUtils.copyProperties( account, vo);
          vo.setExpire(utils.expireTime());
          vo.setToken(token);
//          vo.setRole(account.getRole());
//          vo.setExpire(utils.expireTime());
//          vo.setToken(token);
//          vo.setUsername(account.getUsername());
          response.getWriter().write(RestBean.success(vo).asJsonString());
      }
    public void onLogoutSuccess(HttpServletRequest request,
                                HttpServletResponse response,
                                Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter writer  = response.getWriter();
        String authorization  = request.getHeader("Authorization");
        if(utils.invalidateJwt(authorization)){
           writer.write(RestBean.success().asJsonString());
        } else  {
            writer.write(RestBean.failure(400,"退出登录失败").asJsonString());
        }
      }
      public void onUnauthorized(HttpServletRequest request,
                                 HttpServletResponse response,
                                 AuthenticationException exception) throws IOException {

          response.setContentType("application/json;charset=utf-8");
     response.getWriter().write(RestBean.unauthorized(exception.getMessage()).asJsonString());

      }
      public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException{
          response.setContentType("application/json;charset=utf-8");
          response.getWriter().write(RestBean.unauthorized(exception.getMessage()).asJsonString());

      }

}
